package com.mjk.common.web.getway.restful.prototal.ws.soap.proxy;

import cn.hutool.core.exceptions.ExceptionUtil;
import com.mjk.common.base.error.BizException;
import com.mjk.common.base.response.BeeResponse;
import com.mjk.common.tools.gson.GsonUtils;
import com.mjk.common.tools.xml.XmlUtils;
import com.mjk.common.util.ObjectUtils;
import com.mjk.common.web.getway.constns.GetWayError;
import com.mjk.common.web.getway.constns.GetwayConsts;
import com.mjk.common.web.getway.restful.interceptor.GetWayInterceptorReq;
import com.mjk.common.web.getway.restful.interceptor.type.GetWayInterceptorType;
import com.mjk.common.web.getway.restful.prototal.BaseGetwayInterceptor;
import com.mjk.common.web.getway.restful.prototal.ws.soap.annotation.BeeSoapMethod;
import org.springframework.stereotype.Component;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * 基于soap协议 webservice 的动态代理
 * @author jafek
 *
 */
@Component
public class BeeSoapInvcationHandler extends BaseGetwayInterceptor implements InvocationHandler{
	
	@Override
	public Object invoke(Object proxy, Method method, Object[] args){		
		String proxyName = proxy.getClass().getSimpleName();
		if(proxyName.contains("$")){
			proxyName = proxyName.replace("$Proxy0", "");					
		}
		Map<String,Object> restParams = new HashMap<>();
		BeeSoapMethod soapMethod = method.getAnnotation(BeeSoapMethod.class);
		if(null == soapMethod){
			restParams.put(GetwayConsts.INSTANCE, proxyName);
			restParams.put(GetwayConsts.METHOD, method.getName());			
		}else{
			if(ObjectUtils.isNotEmpty(soapMethod.work())){
				restParams.put(GetwayConsts.INSTANCE, soapMethod.work());
			}else{
				restParams.put(GetwayConsts.INSTANCE, proxyName);
			}
			if(ObjectUtils.isNotEmpty(soapMethod.method())){
				restParams.put(GetwayConsts.METHOD, soapMethod.method());
			}else{
				restParams.put(GetwayConsts.METHOD, method.getName());
			}
		}		
		restParams.put(GetwayConsts.PROTOCOL, GetWayInterceptorType.SOAP.getProto());//设为soap协议
		GetWayInterceptorReq req = new GetWayInterceptorReq();
		//设置restful params
		Map<String,Object> restfulParams = new HashMap<>();
		restfulParams.put(GetwayConsts.PROTOCOL, GetWayInterceptorType.SOAP.getProto());
		req.setRestfulParams(restfulParams);
		req.setProtocal(getWayProtocal);
		if(soapMethod==null) {
			req.setParams(getParams(BeeSoapMethod.ResponseType.JSON,args));
		}else {
			req.setParams(getParams(soapMethod.reqType(),args));
		}
		req.setRestfulParams(restParams);
		BeeResponse result;
		try{
			result = Objects.requireNonNull(GetWayInterceptorType.getGetWayInvoker(req)).invoker(chains.get(GetWayInterceptorType.SOAP.getProto()), req);
		}catch(Exception e){
			BeeResponse response = new BeeResponse();
    	    response.setCode(GetWayError.SOAP_REQ_ERROR.getCode());
			String error = ExceptionUtil.getMessage(e);
    	    response.setMsg(ObjectUtils.isEmpty(error)?GetWayError.SOAP_REQ_ERROR.getMsg():error);
			result = response;
		}
		if(soapMethod==null) {
			return GsonUtils.bean2Json(result);
		}
		if(BeeSoapMethod.ResponseType.JSON.equals(soapMethod.rspType())){
			return GsonUtils.bean2Json(result);
		}else if(BeeSoapMethod.ResponseType.XML.equals(soapMethod.rspType())){
			return XmlUtils.beanToXml(result);
		}else if(BeeSoapMethod.ResponseType.CUSTM.equals(soapMethod.rspType())){
			if(ObjectUtils.isEmpty(result)) {
				return "";
			}else {
				return result.getData();
			}
		}else{
			throw new BizException(GetWayError.DATA_FORMAT_ERROR.getMsg());
		}
		
	}
	
	public Map<String,Object> getParams(BeeSoapMethod.ResponseType type, Object[] args){
		Map<String,Object> params = new HashMap<>();
        for (Object arg : args) {
            if (type.equals(BeeSoapMethod.ResponseType.JSON)) {
                if (GsonUtils.isJson(arg.toString())) {
                    params.putAll(GsonUtils.gson2Map(arg.toString()));
                } else {
                    throw new BizException(GetWayError.DATA_FORMAT_ERROR.getMsg());
                }
            } else if (type.equals(BeeSoapMethod.ResponseType.XML)) {
                if (XmlUtils.isXML(arg.toString())) {
                    Map<String, Object> tmpMap = XmlUtils.xmlToMap(arg.toString());
                    if (tmpMap.containsKey("root")) {
                        params.putAll((Map<String, Object>) tmpMap.get("root"));
                    } else {
                        params.putAll(tmpMap);
                    }

                } else {
                    throw new BizException(GetWayError.DATA_FORMAT_ERROR.getMsg());
                }
            } else if (type.equals(BeeSoapMethod.ResponseType.CUSTM)) {//如果是自定义，用一个固定变量customStr 来保存当前参数
                params.put("customStr", arg.toString());
            }
        }
		return params;
	}
}
